package com.simple.core.service;

import com.simple.core.dto.PageDto;
import com.simple.core.spec.DeleteSpec;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;

import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;

/**
 * Service接口
 *
 * @author FanXing
 * @date 2023年03月01日 19:55
 */
public interface IService<T> {
    /**
     * 查询所有
     *
     * @param ids 实体类ids
     * @return
     */
    List<T> findAll(Collection<Serializable> ids);

    /**
     * 查询所有
     *
     * @param entity 模版实体
     * @return
     */
    List<T> findAll(T entity);

    /**
     * 查询所有
     *
     * @param entity
     * @param sort
     * @return
     */
    List<T> findAll(T entity, Sort sort);

    /**
     * 查询所有
     *
     * @param spec 表达式
     * @return
     */
    List<T> findAll(@Nullable Specification<T> spec);

    /**
     * 查询所有
     *
     * @param spec
     * @param sort
     * @return
     */
    List<T> findAll(@Nullable Specification<T> spec, Sort sort);

    /**
     * 标准查询
     *
     * @param queryConsumer 标准查询
     * @return
     */
    List<T> findAll(BiConsumer<Root<T>, CriteriaQuery<T>> queryConsumer);

    /**
     * 分页查询
     *
     * @param entity
     * @param pageDto
     * @return
     */
    PageDto<T> page(T entity, PageDto pageDto);

    /**
     * 分页查询
     *
     * @param spec
     * @param pageDto
     * @return
     */
    PageDto<T> page(@Nullable Specification<T> spec, PageDto pageDto);

    /**
     * 标准分页查询
     *
     * @param queryConsumer
     * @param pageDto
     * @return
     */
    PageDto<T> page(BiConsumer<Root<T>, CriteriaQuery<?>> queryConsumer, PageDto pageDto);

    /**
     * Feed流查询
     *
     * @param entity
     * @param pageDto
     * @return
     */
    PageDto<T> slice(T entity, PageDto pageDto);

    /**
     * Feed流查询
     *
     * @param spec
     * @param pageDto
     * @return
     */
    PageDto<T> slice(@Nullable Specification<T> spec, PageDto pageDto);

    /**
     * Feed流标准查询
     *
     * @param queryConsumer
     * @param pageDto
     * @return
     */
    PageDto<T> slice(BiConsumer<Root<T>, CriteriaQuery<T>> queryConsumer, PageDto pageDto);

    /**
     * 根据ID查询一个
     *
     * @param id
     * @param <ID>
     * @return
     */
    <ID extends Serializable> Optional<T> findById(ID id);

    /**
     * 查询一个
     *
     * @param entity
     * @return
     */
    Optional<T> findOne(T entity);

    /**
     * 查询一个
     *
     * @param spec
     * @return
     */
    Optional<T> findOne(Specification<T> spec);

    /**
     * 查询一个-标准查询
     *
     * @param queryConsumer
     * @return
     */
    Optional<T> findOne(BiConsumer<Root<T>, CriteriaQuery<T>> queryConsumer);

    /**
     * 保存，新增或更新
     *
     * @param entity
     */
    boolean save(T entity);

    /**
     * 新增
     *
     * @param entity
     * @return
     */
    boolean add(T entity);

    /**
     * 更新
     *
     * @param entity
     * @return
     */
    boolean update(T entity);

    /**
     * 批量新增
     *
     * @param entities
     */
    boolean insertInBatch(Collection<T> entities);

    /**
     * 更新-标准更新
     *
     * @param updateConsumer
     * @return
     */
    int update(BiConsumer<Root<T>, CriteriaUpdate<T>> updateConsumer);

    /**
     * 删除
     *
     * @param deleteSpec
     * @return
     */
    int delete(DeleteSpec<T> deleteSpec);

    /**
     * 通过ID删除
     *
     * @param id
     * @param <ID>
     */
    <ID extends Serializable> boolean deleteById(ID id);

    /**
     * 批量删除
     *
     * @param ids  ID集合
     * @param <ID>
     */
    <ID extends Serializable> boolean deleteAllById(Iterable<ID> ids);

    /**
     * 查询数量
     *
     * @param entity
     * @return
     */
    long count(T entity);

    /**
     * 查询数量
     *
     * @param spec
     * @return
     */
    long count(@Nullable Specification<T> spec);
}
